package tests_ecj;

import ec.EvolutionState;
import ec.Evolve;
import ec.Individual;
import ec.Problem;
import ec.simple.SimpleFitness;
import ec.simple.SimpleProblemForm;
import ec.util.ParameterDatabase;
import ec.vector.BitVectorIndividual;

/**
 * 
 * @author fernando
 *  Build a Genetic Algorithm for the MaxOnes Problem
 */
public class MaxOnes extends Problem implements SimpleProblemForm{

	/**
	 * ECJ's top-level object is ec.Evolve. Evolve has only one purpose: to
	 * initialize a subclass of ec.EvolutionState, set it up, and get it going. 
	 * The entire evolutionary system is contained somewhere within the 
	 * EvolutionState object or a sub-object hanging off of it.
	 */


	private static final long serialVersionUID = 3221702872150043947L;

	/**
	 * executing ECJ programmatically
	 * @param args
	 */
	public static void main(String[] args){
		Evolve.main(new String[]{ "-file", "conf/maxones.params"});
	}

	@Override
	/**
	 * SimpleEvaluator requires that its Problems implement the ec.simple.SimpleProblemForm interface. 
	 * This interface defines two methods, evaluate (required) and describe (optional). 
	 * evaluate takes an individual, evaluates it somehow, sets its fitness, and marks it evaluated. 
	 * describe takes an individual and prints out to a log some information about how the individual operates 
	 * (maybe a map of it running around, or whatever you'd like). describe is called when the statistics wants 
	 * to print out "special" information about the best individual of the generation or of the run, and it's not necessary. 
	 */
	public void evaluate(EvolutionState state, Individual ind, int subpopulation, int threadnum) {
		//don't evaluate the individual if it's already evaluated
		if (ind.evaluated)
			return;

		if (!(ind instanceof BitVectorIndividual))
			state.output.fatal("Not a BitVectorIndividual!!!",null);

		BitVectorIndividual ind2 = (BitVectorIndividual) ind;

		int sum = 0;
		//For BitVectorIndividual, genome is a boolean array. We're simply counting the number of trues in it
		for(int i = 0; i < ind2.genomeLength(); i++){
			sum += ind2.genome[i] ? 1: 0;
		}

		//fitness computation
		if (!(ind2.fitness instanceof SimpleFitness))
			state.output.fatal("Not a SimpleFitness!!!", null);

		//state info record, fitness value, is the individual ideal (max fitness)
		((SimpleFitness)ind2.fitness).setFitness(state, (float)(((double)sum)/ind2.genome.length),	sum == ind2.genome.length);
		ind2.evaluated = true;

	}

	//public void describe(Individual ind, EvolutionState state, int subpopulation, int threadnum, int log,int verbosity){
	//We finish out with an empty version of the describe method, since we don't have anything special to say about individuals:
	//}

}
